﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCAD
{
    public class Jigs
    {
        public class JigLine : DrawJig
        {
            Point3d _po1;
            Point3d _po2;
            Line _line;
            public Arc _arc;
            public JigLine(Point3d po1, Point3d po2)
            {
                _po1 = po1;
                _po2 = po2;
                _line = new Line
                {
                    ColorIndex = 1,
                    LineWeight = LineWeight.LineWeight030
                };
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                PromptPointResult psr = prompts.AcquirePoint();
                if (psr.Status == PromptStatus.OK)
                {
                    Point3d poNow = psr.Value;
                    if (poNow != _po1)
                    {
                        _line.StartPoint = _po1;
                        _line.EndPoint = poNow;
                        Vector3d vector1 = _line.Delta;
                        vector1 = vector1.RotateBy(Math.PI / 2, Vector3d.ZAxis);
                        Line line1 = new Line(_po1, _po1 + vector1);
                        Point3d point = new Point3d(_po1.X / 2 + _po2.X / 2, _po1.Y / 2 + _po2.Y / 2, 0);
                        Vector3d vector2 = _po2 - _po1;
                        vector2 = vector2.RotateBy(Math.PI / 2, Vector3d.ZAxis);
                        Line line2 = new Line(point, point + vector2);
                        Point3dCollection pos = new Point3dCollection();
                        line1.IntersectWith(line2, Intersect.ExtendBoth, pos, IntPtr.Zero, IntPtr.Zero);
                        if (pos.Count == 1)
                        {
                            Point3d center = pos[0];
                            double radius = center.DistanceTo(_po1);
                            Vector3d v1 = _po1 - center;
                            Vector3d v2 = _po2 - center;
                            Vector3d normal = _line.Delta.CrossProduct(center - _po1).GetNormal();
                            double angle1;
                            double angle2;
                            if (normal.Z > 0)
                            {
                                angle1 = v1.GetAngleTo(Vector3d.XAxis, -normal);
                                angle2 = v2.GetAngleTo(Vector3d.XAxis, -normal);
                            }
                            else
                            {
                                angle1 = v1.GetAngleTo(-Vector3d.XAxis, -normal);
                                angle2 = v2.GetAngleTo(-Vector3d.XAxis, -normal);
                            }


                            WCAD.Ed.WriteMessage("\n" + normal.ToString());
                            _arc = new Arc(center, normal, radius, angle1, angle2);
                        }

                        return SamplerStatus.OK;
                    }
                    else
                    {
                        return SamplerStatus.NoChange;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
            {
                draw.Geometry.Draw(_line);
                if (_arc != null)
                {
                    draw.Geometry.Draw(_arc);
                }
                return true;
            }
        }
        public class JigPL : DrawJig
        {
            Point3d _po1;
            Point3d _po2;
            Line _line;
            int _n;
            public Polyline _polyline;

            public JigPL(Polyline polyline, Point3d point)
            {
                _polyline = polyline;
                double p = polyline.GetParameterAtPoint(polyline.GetClosestPointTo(point, false));
                int n = (int)p;
                _n = n;
                _po1 = polyline.GetPoint3dAt(n);
                _po2 = polyline.GetPoint3dAt(n + 1);
                _line = new Line
                {
                    ColorIndex = 1,
                    LineWeight = LineWeight.LineWeight030
                };
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                PromptPointResult psr = prompts.AcquirePoint();
                if (psr.Status == PromptStatus.OK)
                {
                    Point3d poNow = psr.Value;
                    if (poNow != _po1)
                    {
                        _line.StartPoint = _po1;
                        _line.EndPoint = poNow;
                        Vector3d vector1 = _line.Delta;
                        vector1 = vector1.RotateBy(Math.PI / 2, Vector3d.ZAxis);
                        Line line1 = new Line(_po1, _po1 + vector1);
                        Point3d point = new Point3d(_po1.X / 2 + _po2.X / 2, _po1.Y / 2 + _po2.Y / 2, 0);
                        Vector3d vector2 = _po2 - _po1;
                        vector2 = vector2.RotateBy(Math.PI / 2, Vector3d.ZAxis);
                        Line line2 = new Line(point, point + vector2);
                        Point3dCollection pos = new Point3dCollection();
                        line1.IntersectWith(line2, Intersect.ExtendBoth, pos, IntPtr.Zero, IntPtr.Zero);
                        if (pos.Count == 1)
                        {
                            Point3d center = pos[0];
                            double radius = center.DistanceTo(_po1);
                            Vector3d v1 = _po1 - center;
                            Vector3d v2 = _po2 - center;
                            Vector3d normal = _line.Delta.CrossProduct(center - _po1).GetNormal();
                            double bulge = Math.Tan(v1.GetAngleTo(v2, normal) / 4) * normal.Z;
                            _polyline.SetBulgeAt(_n, bulge);
                        }
                        return SamplerStatus.OK;
                    }
                    else
                    {
                        return SamplerStatus.NoChange;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
            {
                draw.Geometry.Draw(_line);
                draw.Geometry.Draw(_polyline);
                return true;
            }
        }
        public class JigRec : DrawJig
        {
            Point3d _po1;
            public Line _line;
            public Polyline _pl;
            public JigRec(Point3d po1)
            {
                _po1 = po1;
                _line = new Line
                {
                    ColorIndex = 1
                };
            }
            public JigRec(Line line)
            {
                _line = line;
                _pl = new Polyline();
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                PromptPointResult psr = prompts.AcquirePoint();
                if (psr.Status == PromptStatus.OK)
                {
                    Point3d poNow = psr.Value;
                    if (poNow != _po1)
                    {
                        if (_pl != null)
                        {
                            Point3d point = _line.GetClosestPointTo(poNow, true);
                            Vector3d vector1 = point.GetVectorTo(_line.EndPoint);
                            Vector3d vector2 = point.GetVectorTo(_line.StartPoint);
                            _pl = new Polyline();
                            _pl.ColorIndex = 1;
                            _pl.AddVertexAt(0, _line.StartPoint.Convert2d(new Plane()), 0, 0, 0);
                            _pl.AddVertexAt(1, _line.EndPoint.Convert2d(new Plane()), 0, 0, 0);
                            _pl.AddVertexAt(2, (poNow + vector1).Convert2d(new Plane()), 0, 0, 0);
                            _pl.AddVertexAt(3, (poNow + vector2).Convert2d(new Plane()), 0, 0, 0);
                            _pl.Closed = true;
                        }
                        else
                        {
                            _line.StartPoint = _po1;
                            _line.EndPoint = poNow;
                        }
                        return SamplerStatus.OK;
                    }
                    else
                    {
                        return SamplerStatus.NoChange;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
            {
                if (_pl != null)
                {
                    draw.Geometry.Draw(_pl);
                }
                else
                {
                    draw.Geometry.Draw(_line);
                }

                return true;
            }
        }

        public class JigEnts : DrawJig
        {
            public List<Entity> _entities = new List<Entity>();
            public Point3d _point;
            public double _dis;
            public int _ind;
            public Entity _ent;
            public Line _line;
            public JigEnts(Point3d point, double dis, Entity ent)
            {
                Hatch hatch = new Hatch();
                hatch.PatternScale = 20;
                hatch.ColorIndex = 256;
                hatch.SetHatchPattern(HatchPatternType.CustomDefined, "Solid");
                ObjectIdCollection ids = new ObjectIdCollection();
                Line line1 = new Line(new Point3d(point.X + dis, point.Y, 0), new Point3d(point.X + dis * 1.2, point.Y, 0));
                for (double i = 0; i < 360.1; i += 0.1)
                {
                    Line line = line1.Clone() as Line;
                    line.Color = RgbColorMethod.RainbowAll(i, 360);
                    Matrix3d matrix3 = Matrix3d.Rotation(Math.PI / 180 * i, Vector3d.ZAxis, point);
                    line.TransformBy(matrix3);
                    _entities.Add(line);
                }
                _ent = ent.Clone() as Entity;
                _ent.Visible = true;
                _point = point;
                _dis = dis;
                _line = new Line();
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                PromptPointResult psr = prompts.AcquirePoint();
                if (psr.Status == PromptStatus.OK)
                {
                    Point3d poNow = psr.Value;
                    if (poNow != _point)
                    {
                        _line = new Line(_point, _point + _point.GetVectorTo(poNow).GetNormal() * _dis * 1.2);
                        Vector3d vector = _point.GetVectorTo(poNow);
                        double ang = vector.GetAngleTo(Vector3d.XAxis, -Vector3d.ZAxis);
                        _ent.Color = RgbColorMethod.RainbowAll(ang, Math.PI * 2);

                        return SamplerStatus.OK;
                    }
                    else
                    {
                        return SamplerStatus.NoChange;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
            {
                _entities.ForEach(x => draw.Geometry.Draw(x));
                draw.Geometry.Draw(_ent);
                draw.Geometry.Draw(_line);
                return true;
            }
        }
        public class JigAll : DrawJig
        {
            public Point3d _point;
            public List<Entity> _ents;
            public Func<Point3d, List<Entity>> _func;
            public JigAll(Point3d point, Func<Point3d, List<Entity>> func)
            {
                _point = point;
                _ents = new List<Entity>();
                _func = func;
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                //JigPromptPointOptions jppo = new JigPromptPointOptions
                //{
                //    Message="1",
                //    BasePoint = _point,
                //    UseBasePoint = true,
                //    Cursor=CursorType.Parallelogram,
                //};
                PromptPointResult psr = prompts.AcquirePoint();
                if (psr.Status == PromptStatus.OK)
                {
                    Point3d poNow = psr.Value;
                    if (poNow != _point)
                    {
                        _ents.Clear();
                        _ents = _func(poNow);
                        return SamplerStatus.OK;
                    }
                    else
                    {
                        return SamplerStatus.NoChange;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
            {
                _ents.ForEach(x => draw.Geometry.Draw(x));
                return true;
            }
        }
        public class JigJig : DrawJig
        {
            private Point3d _point;
            private List<Entity> _ents;
            private List<Entity> _ents1;
            private Action<Point3d, List<Entity>, List<Entity>> _func;
            private string _message;
            private JigPromptPointOptions _jppo;
            private bool _add;
            private bool _stop;
            public JigJig(Point3d point, Action<Point3d, List<Entity>, List<Entity>> func, JigPromptPointOptions jppo = null, string message = "")
            {
                _point = point;
                _ents = new List<Entity>();
                _ents1 = new List<Entity>();
                _func = func;
                _message = message;
                if (jppo == null)
                {
                    _jppo = new JigPromptPointOptions(message);
                    _add = true;
                }
                else
                {
                    _jppo = jppo;
                    _add = false;
                }
                if (_add && WCAD.Ed.Drag(this).Status == PromptStatus.OK)
                {
                    
                    EmEntityMethod.AddEntities(_ents);
                    _stop = false;
                }
                else
                {
                    _stop = true;
                }
            }
            public bool IsStop()
            {
                return _stop;
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                //JigPromptPointOptions jppo = new JigPromptPointOptions(_message)
                //{
                //    BasePoint = _point,
                //    UseBasePoint = true,
                //    Cursor = CursorType.RubberBand,
                //};
                PromptPointResult psr = prompts.AcquirePoint(_jppo);
                if (psr.Status == PromptStatus.OK)
                {
                    Point3d poNow = psr.Value;
                    if (poNow != _point)
                    {
                        _ents.Clear();
                        _ents1.Clear();
                        _func(poNow, _ents, _ents1);
                        return SamplerStatus.OK;
                    }
                    else
                    {
                        return SamplerStatus.NoChange;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
            {
                _ents.ForEach(x => draw.Geometry.Draw(x));
                _ents1.ForEach(x => draw.Geometry.Draw(x));
                return true;
            }
            public List<Entity> GetEntities()
            {
                return _ents;
            }
        }
        
    }
}

